package com.jeeplus.test.jlnu.admissionInfo.controller;

import com.alibaba.excel.EasyExcel;
import com.jeeplus.test.education.domain.vo.EducationInfoVo;
import com.jeeplus.test.jlnu.admissionInfo.domain.entity.*;
import com.jeeplus.test.jlnu.admissionInfo.service.*;
import com.jeeplus.test.jlnu.admissionInfo.utils.*;
import com.jeeplus.test.jlnu.deanOffice.domain.entity.JlnuDeansOffice;
import com.jeeplus.test.jlnu.mailingInfo.domain.vo.MailingInfoVo;
import com.jeeplus.test.jlnu.mailingInfo.service.MailingInfoService;
import com.jeeplus.test.jlnu.xlsxManage.service.JlnuXlsxManageService;
import com.jeeplus.test.postgraduate.domain.vo.PostgraduateReqVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
@RestController
@RequestMapping("/excel")
public class ExcelController {

    @Autowired
    private ExcelService excelService;
    @Autowired
    private ExcelServiceStu excelServiceStu;
    @Autowired
    private ContinueService continueService;
    @Autowired
    private StudentsOfficeService studentsOfficeService;
    @Autowired
    private JlnuXlsxManageService xlsxManageService;

    @Autowired
    private AdmissionExcelService admissionExcelService;

    @Autowired
    private ExcelServiceDean excelServiceDean;

    @Autowired
    private MailingInfoService mailingInfoService;

    @Autowired
    private MyWebSocketHandler webSocketHandler;

    private final ExecutorService executor = Executors.newSingleThreadExecutor();


    @GetMapping("/download/regisyrarTemplate")
    public ResponseEntity<byte[]> downloadTemplate() throws IOException {
        // 使用 ClassPathResource 从 resources 目录读取文件
        Resource resource = new ClassPathResource("static/教务处导入模板.xlsx");

        // 获取输入流
        InputStream inputStream = resource.getInputStream();

        // 将输入流转换为字节数组
        byte[] fileData = FileCopyUtils.copyToByteArray(inputStream);

        // 设置 HTTP 响应头，指示文件下载
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=import_template.xlsx");
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(fileData.length) // 使用字节数组的长度
                .body(fileData);
    }

    /**
     * 下载继续教育学院导入模板
     * @return
     * @throws IOException
     */
    @GetMapping("/download/continueTemplate")
    public ResponseEntity<byte[]> continueTemplate() throws IOException {
        // 使用 ClassPathResource 从 resources 目录读取文件
        Resource resource = new ClassPathResource("static/1.xlsx");

        // 获取输入流
        InputStream inputStream = resource.getInputStream();

        // 将输入流转换为字节数组
        byte[] fileData = FileCopyUtils.copyToByteArray(inputStream);

        // 设置 HTTP 响应头，指示文件下载
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=import_template.xlsx");
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(fileData.length) // 使用字节数组的长度
                .body(fileData);
    }

    @GetMapping("/download/GraduationTemplate")
    public ResponseEntity<byte[]> GraduationTemplate() throws IOException {
        // 使用 ClassPathResource 从 resources 目录读取文件
        Resource resource = new ClassPathResource("static/研究生院.xlsx");

        // 获取输入流
        InputStream inputStream = resource.getInputStream();

        // 将输入流转换为字节数组
        byte[] fileData = FileCopyUtils.copyToByteArray(inputStream);

        // 设置 HTTP 响应头，指示文件下载
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=import_template.xlsx");
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(fileData.length) // 使用字节数组的长度
                .body(fileData);
    }

    @GetMapping("/download/admissionTemplate")
    public ResponseEntity<byte[]> admissionTemplate() throws IOException {
        // 使用 ClassPathResource 从 resources 目录读取文件
        Resource resource = new ClassPathResource("static/录取信息模板.xlsx");

        // 获取输入流
        InputStream inputStream = resource.getInputStream();

        // 将输入流转换为字节数组
        byte[] fileData = FileCopyUtils.copyToByteArray(inputStream);

        // 设置 HTTP 响应头，指示文件下载
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=import_template.xlsx");
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(fileData.length) // 使用字节数组的长度
                .body(fileData);
    }

    //单行模板下载
    @GetMapping("/download/rowCustomizeTemplate")
    public ResponseEntity<byte[]> rowCustomizeTemplate(@RequestParam Integer id) throws IOException {


        // 使用 ClassPathResource 从 resources 目录读取文件
        Resource resource = xlsxManageService.rowCustomizeTemplate(id);
        if (resource == null) {
            return ResponseEntity.notFound().build();
        }

        // 获取输入流
        InputStream inputStream = resource.getInputStream();

        // 将输入流转换为字节数组
        byte[] fileData = FileCopyUtils.copyToByteArray(inputStream);

        // 设置 HTTP 响应头，指示文件下载
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=import_template.xlsx");
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(fileData.length) // 使用字节数组的长度
                .body(fileData);
    }

    @GetMapping("/download/customizeTemplate")
    public ResponseEntity<byte[]> customizeTemplate(@RequestParam Integer id) throws IOException {


        // 使用 ClassPathResource 从 resources 目录读取文件
        Resource resource = xlsxManageService.customizeTemplate(id);
        if (resource == null) {
            return ResponseEntity.notFound().build();
        }

        // 获取输入流
        InputStream inputStream = resource.getInputStream();

        // 将输入流转换为字节数组
        byte[] fileData = FileCopyUtils.copyToByteArray(inputStream);

        // 设置 HTTP 响应头，指示文件下载
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=import_template.xlsx");
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(fileData.length) // 使用字节数组的长度
                .body(fileData);
    }

    /**
     * 教务处导入
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/import")
    public ResponseEntity<String> importExcel(
            @RequestParam("file") MultipartFile file,
            @RequestParam("officeId") String officeId,
            //importType参数表示前端在哪个模块下导入的数据。用于逻辑区分
            //（值为DBMS表示数据管理）
            @RequestParam("type") String importType,
            @RequestParam("templateInfoType") String templateInfoType,
            @RequestParam(value = "templateId",required = false,defaultValue = "631") Integer templateId
    ) throws IOException {
        // 清除之前的进度
        webSocketHandler.sendProgressUpdate(0);

        // 读取总记录数（如果可用）
        int totalRecords = getTotalRecords(file);

        // 提交异步任务
        executor.submit(() -> {
            try {
                // 使用 EasyExcel 读取文件，并在处理过程中更新进度
                EasyExcel.read(file.getInputStream(), JlnuDeansOffice.class, new DeanOfficeDataListener(
                        excelServiceDean,
                        progress -> {
                            try {
                                webSocketHandler.sendProgressUpdate(progress);
                            } catch (IOException e) {
                                log.error("进度更新失败: {}", e.getMessage());
                            }
                        },
                        totalRecords,
                        1,
                        null,
                        officeId,
                        importType,
                        templateInfoType,
                        templateId
                )).sheet().headRowNumber(1).doRead();

                // 完成处理后更新进度
                webSocketHandler.sendProgressUpdate(100);
                log.info("Excel 导入完成");

            } catch (Exception e) {
                log.error("Excel 导入失败: {}", e.getMessage());
                try {
                    webSocketHandler.sendProgressUpdate(-1); // 使用 -1 表示失败
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            }
        });

        return ResponseEntity.ok("导入已开始");
    }


    private int getTotalRecords(MultipartFile file) {
        int totalRecords = 0;
        try (InputStream inputStream = file.getInputStream();
             Workbook workbook = WorkbookFactory.create(inputStream)) {

            // 获取第一个工作表
            Sheet sheet = workbook.getSheetAt(0);

            // 计算行数
            totalRecords = sheet.getPhysicalNumberOfRows(); // 包括表头行数

            // 如果不需要计算表头的行数
            // totalRecords = sheet.getLastRowNum(); // 不包括表头
        } catch (IOException e) {
            e.printStackTrace();
            // 处理异常逻辑
        }
        return totalRecords;
    }

    /**
     * 继续教育学院导入
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/importContinue")
    public ResponseEntity<String> importContinue(@RequestParam("file") MultipartFile file,
                                                 @RequestParam("officeId") String officeId,
                                                 //importType参数表示前端在哪个模块下导入的数据。用于逻辑区分
                                                 //（值为DBMS表示数据管理）
                                                 @RequestParam("type") String importType,
                                                 @RequestParam("templateInfoType") String templateInfoType,
                                                 @RequestParam(value = "templateId",required = false,defaultValue = "631") Integer templateId

    ) throws IOException {
        // 清除之前的进度
        webSocketHandler.sendProgressUpdate(0);
        int totalRecords = getTotalRecords(file);

        executor.submit(() -> {
            try {
                // 获取第一个 WebSocket 会话
                WebSocketSession session = webSocketHandler.getFirstWebSocketSession();
                if (session != null) {
                    EasyExcel.read(file.getInputStream(), EducationInfoVo.class, new ContinueDataListener(
                                    continueService, totalRecords, officeId,importType,templateInfoType, webSocketHandler,templateId))
                            .sheet().headRowNumber(1).doRead();

                    webSocketHandler.sendProgressUpdate(100);
                } else {
                    webSocketHandler.sendProgressUpdate(-1); // 如果没有 WebSocket 会话，发送错误信息
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        return ResponseEntity.ok("导入已开始");
    }

    /**
     * 研究生院导入
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/importEducation")
    public ResponseEntity<String> importEducation(@RequestParam("file") MultipartFile file,
                                                  @RequestParam("officeId") String officeId,
                                                  //importType参数表示前端在哪个模块下导入的数据。用于逻辑区分
                                                  //（值为DBMS表示数据管理）
                                                  @RequestParam("type") String importType,
                                                  @RequestParam("templateInfoType") String templateInfoType,
                                                  @RequestParam(value = "templateId",required = false,defaultValue = "631") Integer templateId
                                                  ) throws IOException {
        // 清除之前的进度
        webSocketHandler.sendProgressUpdate(0);
        int totalRecords = getTotalRecords(file);

        try {
            EasyExcel.read(file.getInputStream(), PostgraduateReqVo.class, new StudentInfoDataListener(excelServiceStu, progress -> {
                try {
                    webSocketHandler.sendProgressUpdate(progress);
                } catch (IOException e) {
                    //e.printStackTrace();
                }
            }, totalRecords,officeId,importType,templateInfoType,templateId)).sheet().headRowNumber(1).doRead();
            webSocketHandler.sendProgressUpdate(100);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return ResponseEntity.ok("导入已开始");
    }
    /**
     * 学生处院导入
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/importStuOffice")
    public ResponseEntity<String> importStuOffice(@RequestParam("file") MultipartFile file,@RequestParam("officeId") String officeId) throws IOException {
        // 清除之前的进度
        webSocketHandler.sendProgressUpdate(0);
        int totalRecords = getTotalRecords(file);

        executor.submit(() -> {
            try {
                EasyExcel.read(file.getInputStream(), StudentsOffice.class, new StudentsOfficeDataListener(studentsOfficeService, progress -> {
                    try {
                        webSocketHandler.sendProgressUpdate(progress);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }, totalRecords,officeId)).sheet().headRowNumber(1).doRead();
                webSocketHandler.sendProgressUpdate(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        return ResponseEntity.ok("导入已开始");
    }

    /**
     * 导入录取信息数据
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/importAdmission")
    public ResponseEntity<String> importAdmission(@RequestParam("file") MultipartFile file) throws IOException {
        // 清除之前的进度
        webSocketHandler.sendProgressUpdate(0);
        int totalRecords = getTotalRecords(file);

        executor.submit(() -> {
            try {
                EasyExcel.read(file.getInputStream(), AdmissionInfo.class, new AdmissionDataListener(admissionExcelService, progress -> {
                    try {
                        webSocketHandler.sendProgressUpdate(progress);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }, totalRecords)).sheet().doRead();
                webSocketHandler.sendProgressUpdate(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        return ResponseEntity.ok("导入已开始");
    }
    @PostMapping("/importMailing")
    public ResponseEntity<String> importMailing(@RequestParam("file") MultipartFile file) throws IOException{
        webSocketHandler.sendProgressUpdate(0);
        int totalRecords = getTotalRecords(file);
        executor.submit(() ->{
            try {
                EasyExcel.read(file.getInputStream(), MailingInfoVo.class , new MailingInfoListener(mailingInfoService , progress -> {
                    try {
                        webSocketHandler.sendProgressUpdate(progress);
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                },totalRecords)).sheet().doRead();
                webSocketHandler.sendProgressUpdate(100);
            }catch (Exception e){
                e.printStackTrace();
            }
        });
        return ResponseEntity.ok("导入已开始");
    }

    /**
     * 清空所有业务表 此接口只作为开发环境使用
     */
    @GetMapping("deleteDatabase")
    public void deleteDatabase(){
        excelService.deleteDatabase();
    }
}
